package com.shiro.tqw.shiro1;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class testMultiCustomRealm {
	private Logger logger;
	@Before
	public void beforeHelloword(){
		 logger = LoggerFactory.getLogger(LoginLogoutTest.class);
	}
	
	/**
	 * 1:这里我们用Debug as -->Junit test运行。并且在MyRealm1,MyRealm2中添加断点
	 * 2:跟踪多个Realm时，SecurityManager 获取Realm验证的顺序。
	 * 3:在shiro-multi-realm.ini中的 securityManager.realms=$myRealm1,$myRealm2 前添加#
	 *   号注释掉这一行。再次调试运行。它还是会执行MyRealm1,MyRealm2.
	 *   说明:SecurityManager能自动发现配置在ini文件中的Realm域。
	 * 4：调换一下shiro-multi-realm.ini中Myrealm1,Myrealm2的先后顺序再执行,就会发现执行顺序也变了.
	 * 5:然后我们再次去掉securityManager.realms=$myRealm1,$myRealm2前的注释，再执行
	 *   调用顺序变成了myRealm1,myRealm2了。即执行顺序以securityManager.realms指定的顺序执行
	 * 6:把securityManager.realms=$myRealm1,$myRealm2中的,$myRealm2删除改成
	 * 	 securityManager.realms=$myRealm1.再执行,发现不再调用myRealm2了。
	 *   即表示securityManager,只读取securityManager.realms指定的Realm,没有指定的不会读取
	 * 7:从上述调用的结果来看。会在myRealm1中抛出异常。但在myRealm2中验证通过。
	 *   最后subject仍登陆成功了。由于有多个realm到底以那个realm为准呢？这里涉及到一个验证的策略问题。
	 * 8:另外我们还发现一个问题。我们的realm信息一般存储在 数据库中。那么我们怎么将数据库中的用户名密码和权限信息
	 *   交给shiro来处理呢？
	 * 9：首先，先解决shiro与数据库结合的问题后。再来解决多Realm时的验证策略问题.  
	 */
	@Test
	public void testMultiRealm(){
		Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-multi-realm.ini");
		SecurityManager securityManager = factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);		
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken("wang", "123456");
		try {
			// 4、登录，即身份验证
			subject.login(token);
		} catch (AuthenticationException e) {
			// 5、身份验证失败
			e.printStackTrace();
		}
		
		logger.info("-----------User [" + subject.getPrincipal() + "] logged in successfully.---------");
		Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
		subject.logout();
		logger.info("testCustomRealm end token:" +token);	
	}
}
